﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using BrainTechLLC;
using System.Windows.Threading;
using System.Windows;
using BrainTechLLC.ThreadSafeObjects;
using System.Threading;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;

namespace BrainTechLLC.WPF
{
    [Serializable]
    [DataContract]
    public partial class MultiGenericViewModelBase<TViewModel, T1, T2, T3> : MultiViewModelBase
        where T1 : BaseNotifyPropertyChanged
        where T2 : BaseNotifyPropertyChanged
        where T3 : BaseNotifyPropertyChanged
        where TViewModel : BaseNotifyPropertyChanged
    {
        public static ThreadSafeListAndLookup<string, string> _alsoRaisePropertiesLookup;

        static MultiGenericViewModelBase()
        {
            _alsoRaisePropertiesLookup = new ThreadSafeListAndLookup<string, string>();
            typeof(T1).WireUpAlsoRaisePropertiesLookup(_alsoRaisePropertiesLookup);
            typeof(T2).WireUpAlsoRaisePropertiesLookup(_alsoRaisePropertiesLookup);
            typeof(T3).WireUpAlsoRaisePropertiesLookup(_alsoRaisePropertiesLookup);
            typeof(TViewModel).WireUpAlsoRaisePropertiesLookup(_alsoRaisePropertiesLookup);
        }

        protected T1 _Item1;

        public T1 Item1
        {
            get { return _Item1; }
            set
            {
                if (_Item1 != value)
                {
                    if (_Item1 != null)
                    {
                        _Item1.PropertyChanged -= _Item1_PropertyChanged;                        
                    }

                    _Item1 = value;
                    _Object[0] = value;

                    if (_Item1 != null)
                    {
                        _Item1.PropertyChanged += new PropertyChangedEventHandler(_Item1_PropertyChanged);
                    }

                    OnPropertyChangedUIThread("Item1");
                }
            }
        }

        protected T2 _Item2;

        public T2 Item2
        {
            get { return _Item2; }
            set
            {
                if (_Item2 != value)
                {
                    if (_Item2 != null)
                    {
                        _Item2.PropertyChanged -= _Item2_PropertyChanged;
                    }

                    _Item2 = value;
                    _Object[1] = value;

                    if (_Item2 != null)
                    {
                        _Item2.PropertyChanged += new PropertyChangedEventHandler(_Item2_PropertyChanged);
                    }

                    OnPropertyChangedUIThread("Item2");
                }
            }
        }

        protected T3 _Item3;

        public T3 Item3
        {
            get { return _Item3; }
            set
            {
                if (_Item3 != value)
                {
                    if (_Item3 != null)
                    {
                        _Item3.PropertyChanged -= _Item3_PropertyChanged;
                    }

                    _Item3 = value;
                    _Object[1] = value;

                    if (_Item3 != null)
                    {
                        _Item3.PropertyChanged += new PropertyChangedEventHandler(_Item3_PropertyChanged);
                    }

                    OnPropertyChangedUIThread("Item3");
                }
            }
        }

        protected void _Item1_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChangedUIThread(e.PropertyName);
            OnItemRaisedPropertyChanged(e.PropertyName);
        }

        protected void _Item2_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChangedUIThread(e.PropertyName);
            OnItemRaisedPropertyChanged(e.PropertyName);
        }

        protected void _Item3_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChangedUIThread(e.PropertyName);
            OnItemRaisedPropertyChanged(e.PropertyName);
        }

        public MultiGenericViewModelBase()
        {
            this.PropertyChanged += new PropertyChangedEventHandler(MultiGenericViewModelBase_PropertyChanged);
        }

        public MultiGenericViewModelBase(T1 item1, T2 item2, T3 item3) : this()
        {
            _Object = new List<object>(2);
            _Object.Add(item1);
            _Object.Add(item2);
            _Object.Add(item3);
            Item1 = item1;
            Item2 = item2;
            Item3 = item3;
        }

        void MultiGenericViewModelBase_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != null)
            {
                this.CheckAlsoRaise(e.PropertyName, _alsoRaisePropertiesLookup);
            }            
        }

        public override void OnItemRaisedPropertyChanged(string propertyName)
        {
            if (propertyName != null)
            {
                this.CheckAlsoRaise(propertyName, _alsoRaisePropertiesLookup);
            }

            base.OnItemRaisedPropertyChanged(propertyName);
        }
    }
}
